// 18.2 静态多态（Static Polymorphism）
// 静态多态是 C++ 模板提供的一种多态机制，它在编译期而非运行期实现"一个接口，多种行为"的特性。下面我将详细解释静态多态的概念、实现方式和优缺点。

// --------------------------------------------------
// 静态多态的基本概念
// 静态多态（也称为编译期多态）是指在编译期间确定函数调用，而不是在运行时通过虚函数表查找。它主要通过以下方式实现：
// 1.模板：为不同类型生成不同的代码
// 2.函数重载：根据参数类型选择不同的函数
// 3.CRTP（奇异递归模板模式）：一种特殊的模板技术

// --------------------------------------------------
// 静态多态的实现方式
// 1. 基于模板的静态多态
// 不要求继承关系，只要求有draw()方法
template<typename T>
void drawShape(const T& shape) {
    shape.draw();  // 编译期绑定
}

class Circle {
public:
    void draw() const {
        std::cout << "Drawing a circle\n";
    }
};

class Rectangle {
public:
    void draw() const {
        std::cout << "Drawing a rectangle\n";
    }
};

// 使用
Circle c;
Rectangle r;
drawShape(c);  // 调用 Circle::draw()
drawShape(r);  // 调用 Rectangle::draw()

// 这种方式不要求类之间有继承关系，只要它们提供相同的接口（这里是 draw() 方法）。这种基于接口语义而非继承关系的多态也被称为"鸭子类型"（Duck Typing）。

// 2. CRTP（奇异递归模板模式）
// CRTP 是一种更结构化的静态多态实现方式，它通过让派生类作为模板参数传递给基类来实现：
// 基类模板
template<typename Derived>
class Shape {
public:
    void draw() const {
        // 静态转换到派生类并调用其实现
        static_cast<const Derived*>(this)->drawImpl();
    }
    
    // 默认实现（可选）
    void drawImpl() const {
        std::cout << "Drawing a generic shape\n";
    }
};

// 派生类
class Circle : public Shape<Circle> {
public:
    // 覆盖基类的实现
    void drawImpl() const {
        std::cout << "Drawing a circle\n";
    }
};

class Rectangle : public Shape<Rectangle> {
public:
    void drawImpl() const {
        std::cout << "Drawing a rectangle\n";
    }
};

// 使用
Circle c;
Rectangle r;
c.draw();  // 调用 Circle::drawImpl()
r.draw();  // 调用 Rectangle::drawImpl()

// 3. 概念（Concepts，C++20）
// C++20 引入了概念（Concepts），它提供了更强大的静态多态支持：
// 定义一个概念
template<typename T>
concept Drawable = requires(const T& t) {
    { t.draw() } -> std::same_as<void>;
};

// 使用概念约束模板
template<Drawable T>
void drawShape(const T& shape) {
    shape.draw();
}


// -----------------------------------------------------
// 静态多态与动态多态的对比
// 静态多态的优点
// 1.性能更好：没有虚函数调用的开销
// 2.内联优化：编译器可以内联函数调用
// 3.类型安全：类型错误在编译期就能发现
// 4.接口不明确：没有显式的接口定义

// -----------------------------------------------------
// 何时使用静态多态
// 静态多态适合以下场景：
// 1.性能关键的应用：游戏引擎、实时系统、高性能计算
// 2.编译期已知类型：当使用的类型在编译时已确定
// 3.泛型编程：需要高度通用的代码
// 4.元编程：需要在编译期进行复杂计算


// -----------------------------------------------------
// 总结
// 静态多态是 C++ 模板提供的强大特性，它通过在编译期确定函数调用来避免运行时开销。与动态多态相比，静态多态提供了更好的性能，但缺乏运行时的灵活性。理解这两种多态机制的优缺点，可以帮助我们在不同场景下做出合适的设计选择。